Vue组件递归

您所在的位置:网站首页 vue 引用组件 Vue组件递归

Vue组件递归

#Vue组件递归| 来源: 网络整理| 查看: 265

不知道大家有没遇到过这样的场景:渲染列表数据的时候,列表的子项还是列表。如果层级少尚且可以用几个for循环搞定,但是层级多或者层级不确定就有点无从下手了。

其实这就是树形结构数据,像常见的组织架构图,文件夹目录,导航菜单等都属于这种结构。很多组件库都带有树形组件,但往往样式不是我们想要的,改起来也非常的费劲。那么,如何自己渲染这些数据呢?答案就是——组件递归!

效果展示

组件递归 00_00_00-00_00_30~2.gif

以上就是使用组件递归,并加入简单交互的展示效果。点击节点会在控制台输出节点对应的数据,如果有子节点,则会展开或收起子节点。接下来我们就看看如何实现以上效果吧!

渲染完整数据

渲染数据这一步非常简单,首先是把树形结构封装成一个列表组件,其次判断每一项有没有子节点,如果有子节点,再使用自身组件去渲染就可以了。

src/components/myTree.vue

{{ item.name }} export default { name: 'myTree', props: { treeData: { type: Array, default: () => [] } } } .tree-item { .item-title { padding: 4px 8px; } .item-childen { padding-left: 20px; } } 复制代码

src/App.vue

const treeData = [ { id: 1, name: '一级1' }, { id: 2, name: '一级2', children: [ { id: 3, name: '二级2-1' }, { id: 4, name: '二级2-2' } ] }, { id: 5, name: '一级3', children: [ { id: 6, name: '二级3-1', children: [ { id: 7, name: '三级3-1-1' }, { id: 8, name: '三级3-1-2' } ] }, { id: 9, name: '二级3-2' }, { id: 10, name: '二级3-3' } ] } ] import myTree from '@/components/myTree.vue' export default { components: { myTree }, data() { return { treeData: treeData } } } 复制代码 效果如下

1642913680(1).jpg

获取节点数据

接下来我们要做的是,点击节点时在控制台输出对应的数据。首先我们使用 $emit,将一级节点的 item 传递出去,也就是子传父的方法,相信大家都会。

其次是将内层节点的数据传递出去,同样使用子传父的方法,只是我们需要给组件里面的 my-tree 绑定@node-click="$emit('node-click', $event)",这样每次子级每次都可以调用父级的 node-click 方法,父级又调用它的父级 node-click 方法,最终调的都是最外层的 node-click 方法,我们只需要在这个过程中,把数据传递过去就可以了。这块有点绕,相信大家多看几遍应该可以看懂。修改如下:

src/components/myTree.vue

{{ item.name }} ... itemNodeClick(item) { this.$emit("node-click", item) } 复制代码

src/App.vue

... nodeClick(val) { console.log(val) } 复制代码 效果如下

组件递归2 00_00_00-00_00_30.gif

动态展开收起

这一步的思路是给组件设置一个数组,数组中存放的是当前列表中需要展开的节点的id,当点击节点的时候添加或删除节点id,然后判断每个节点的id在不在这个数组,在则显示子节点,不在则隐藏子节点。

src/components/myTree.vue

{{ item.name }} [{{ isOpen(item.id) ? '-' : '+' }}] ... data() { return { expandedKeys: [] // 当前列表需要展开的节点id组成的数组 } }, methods: { nodeClick(item) { this.$emit('node-click', item) if (item.children && item.children.length) { let index = this.expandedKeys.indexOf(item.id) if (index > -1) { // 如果当前节点id存在数组中,则删除 this.expandedKeys.splice(index, 1) } else { // 如果当前节点id不存在数组中,则添加 this.expandedKeys.push(item.id) } } }, isOpen(id) { // 判断节点id在不在数组中,在则显示,不在则隐藏 return this.expandedKeys.includes(id) } } 复制代码 效果如下

组件递归3 00_00_00-00_00_30~1.gif

最后我们再添加一些样式,就大功告成啦!

完整代码

src/components/myTree.vue

{{ item.name }} [{{ isOpen(item.id) ? '-' : '+' }}] export default { name: 'myTree', props: { treeData: { type: Array, default: () => [] } }, data() { return { expandedKeys: [] // 当前展开的节点id组成的数组 } }, methods: { nodeClick(item) { this.$emit('node-click', item) if (item.children && item.children.length) { let index = this.expandedKeys.indexOf(item.id) if (index > -1) { // 如果当前节点id存在数组中,则删除 this.expandedKeys.splice(index, 1) } else { // 如果当前节点id不存在数组中,则添加 this.expandedKeys.push(item.id) } } }, isOpen(id) { // 判断节点id在不在数组中,在则显示,不在则隐藏 return this.expandedKeys.includes(id) } } } .tree-item { cursor: pointer; .item-title { padding: 4px 8px; &:hover { background: #eee; } } .item-childen { padding-left: 20px; } } 复制代码

src/App.vue

const treeData = [ { id: 1, name: '一级1' }, { id: 2, name: '一级2', children: [ { id: 3, name: '二级2-1' }, { id: 4, name: '二级2-2' } ] }, { id: 5, name: '一级3', children: [ { id: 6, name: '二级3-1', children: [ { id: 7, name: '三级3-1-1' }, { id: 8, name: '三级3-1-2' } ] }, { id: 9, name: '二级3-2' }, { id: 10, name: '二级3-3' } ] } ] import myTree from '@/components/myTree.vue' export default { components: { myTree }, data() { return { treeData: treeData } }, methods: { nodeClick(val) { console.log(val) } } } 复制代码 效果如下

组件递归 00_00_00-00_00_30~2.gif

以上就是今天的分享!有兴趣的小伙伴可以动手试一哈,把组件进一步封装,或修改成自己想要的样式。 Vue官方的树形视图

如果觉得有用,不要忘了点个赞呦!年前最后一次更文了,提前祝大家新春快乐!爱情、事业虎虎生威(~ ̄▽ ̄)↗

Demo地址:github.com/frontend-af…



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3